
var TestLoSPlayground = TestLoSMapBase.extend({
    ctor:function () {
        this._super();
        //
        this._initTextOnTheGroud();
    },
    _initData:function() {
        this._super();
        this._targets = [];
        this._lightSources = [];
    },
    _initMainLayer:function() {
        this._mainLayer = new cc.LayerColor(cc.color(255, 0, 0, 0), 1600, 1200);
        this.addChild(this._mainLayer, 1);
        //
        this._gridLine = new cc.Sprite(res.gridLine_png);
        this._gridLine.ignoreAnchorPointForPosition(true);
        this._gridLine.setPosition(0, 0);
        this._gridLine.setOpacity(200);
        this._mainLayer.addChild(this._gridLine);
    },
    _initFloatingMenu:function() {
        this._super();

        this._editorTextPanelItem = new ssr.TextPanelItem(
            "  --- Editor ---",
            cc.sys.isNative ? cc.MenuItemFont.getFontName(): cc.MenuItemFont.fontName(), 
            cc.sys.isNative ? cc.MenuItemFont.getFontSize(): cc.MenuItemFont.fontSize()
        );

        this._polyEditorMenuPanelItem = new ssr.ToggleMenuPanelItem(
            [
                "  Poly Editor Off",
                "  Poly Editor On"
            ], this._polyEditorMenuCallback, this
        );
        this._freeDrawingMenuPanelItem = new ssr.ToggleMenuPanelItem(
            [
                "  Free Drawing Off",
                "  Free Drawing On"
            ], this._freeDrawingMenuCallback, this
        );
        this._othersTextPanelItem = new ssr.TextPanelItem(
            "  --- Others ---",
            cc.sys.isNative ? cc.MenuItemFont.getFontName(): cc.MenuItemFont.fontName(), 
            cc.sys.isNative ? cc.MenuItemFont.getFontSize(): cc.MenuItemFont.fontSize()
        );
        // 是否跟随
        this._followPanelItem = new ssr.ToggleMenuPanelItem(
            [
                "  × Follow",
                "  ○ Follow", 
            ], this._followMenuCallback, this
        );
        this._addFlagMenuPanelItem = new ssr.MenuPanelItem(
            "  Add Flag", 
            this._addFlagMenuCallback, this
        );
        this._removeFlagMenuPanelItem = new ssr.MenuPanelItem(
            "  Remove Flags", 
            this._removeFlagsMenuCallback, this
        );
        this._addLightMenuPanelItem = new ssr.MenuPanelItem(
            "  Add Light", 
            this._addLightMenuCallback, this
        );
        this._removeLightsMenuPanelItem = new ssr.MenuPanelItem(
            "  Remove Lights", 
            this._removeLightsMenuCallback, this
        );
        this._importMenuPanelItem = new ssr.MenuPanelItem(
            "  Import", 
            this._importMenuCallback, this
        );
        this._exportMenuPanelItem = new ssr.MenuPanelItem(
            "  Export", 
            this._exportMenuCallback, this
        );

        this._floatingMenu.addItems(
            this._editorTextPanelItem,
            this._polyEditorMenuPanelItem,
            this._freeDrawingMenuPanelItem,
            this._othersTextPanelItem,
            this._followPanelItem,
            this._addFlagMenuPanelItem,
            this._removeFlagMenuPanelItem,
            this._addLightMenuPanelItem,
            this._removeLightsMenuPanelItem,
            this._importMenuPanelItem,
            this._exportMenuPanelItem
        );
    },
    _initTextOnTheGroud:function() {
        var textArray = [
            "Cocos2d-x",
            "SSRLoS",
            "SuperSuRaccoon",
            "cc.ClippingNode",
            "cc.DrawNode",
            "cc.GLProgram",
            "Algorithm",
            "Line-of-Sight",
            "Field-of-View",
            "Math",
            "Vector",
        ];
        for (var i = 0; i < textArray.length; i ++) {
            var labelOnTheGroud = new cc.LabelTTF(textArray[i], MENU_FONT_NAME, cc.sys.isNative ? 24 : 24);
            labelOnTheGroud.setColor(cc.color("#00EEEE"));
            labelOnTheGroud.setOpacity(255);
            if (i < 3) {
                labelOnTheGroud.setPosition(
                    100 + Math.random() * (cc.winSize.width - 200), 
                    100 + Math.random() * (cc.winSize.height - 200)
                );
            }
            else {
                labelOnTheGroud.setPosition(
                    100 + Math.random() * (this._mainLayer.width - 200), 
                    100 + Math.random() * (this._mainLayer.height - 200)
                );
            }
            this._mainLayer.addChild(labelOnTheGroud);
        }
    },
    _processRobotSight:function(dt) {
        this._super(dt);
        // process targets
        if (this._robotObject.getLoSComponentCore().isUpdated()) {
            for (var i = 0; i < this._targets.length; i ++) {
                if (this._robotObject.getLoSComponentCore().isPointVisible(this._targets[i].getPosition())) {
                    this._targets[i].setColor(cc.color.GREEN);
                }
                else {
                    this._targets[i].setColor(cc.color.WHITE);
                }
            }
        }
        // process lights
        for (var i = 0; i < this._lightSources.length; i ++) {
            this._lightSources[i].updateSightNode();
            if (this._losMaskNode.isVisible()) {
                this._losMaskNode.updateTarget(this._lightSources[i], (this._lightSources[i].needForceUpdate() && this._isForceLoSUpdate));
                this._lightSources[i].resetNeedForceUpdate();
            }
        }
    },
    obstacleRemoveCallback:function(obstacleNode) {
        var obstacle = this._robotObject.getLoSComponentCore().findObstacle(obstacleNode);
        if (!obstacle || obstacle.isDirtyDetectionOn()) {
            return;
        }
        this._robotObject.getLoSComponentCore().removeObstacle(obstacleNode);
    },
    obstacleVertexUpdateCallback:function(obstacleNode, vertexIndex, oldPosition, newPosition) {
        var obstacle = this._robotObject.getLoSComponentCore().findObstacle(obstacleNode);
        if (!obstacle || obstacle.isDirtyDetectionOn()) {
            return;
        }
        var vertexArray = obstacleNode.getVertexArray(true);
        this._robotObject.getLoSComponentCore().updateObstacle(obstacleNode, vertexArray);
    },
    obstacleUpdatedCallback:function(obstacleNode) {
        var obstacle = this._robotObject.getLoSComponentCore().findObstacle(obstacleNode);
        if (!obstacle || obstacle.isDirtyDetectionOn()) {
            return;
        }
        var vertexArray = obstacleNode.getVertexArray(true);
        this._robotObject.getLoSComponentCore().updateObstacle(obstacleNode, vertexArray);
    },
    _initPolygonEditor:function() {
        this._polygonEditorVertexArray = [];
        this._drawNodeVertices = new cc.DrawNode();
        this._drawNodePoly = new cc.DrawNode();
        this.addChild(this._drawNodePoly, 11);
        this.addChild(this._drawNodeVertices, 11);
        var self = this;
        this._polygonEditorEvent = cc.eventManager.addListener({
            event: cc.EventListener.TOUCH_ONE_BY_ONE,
            swallowTouches: true,
            onTouchBegan: function (touch, event) {
                var mapPosition = touch.getLocation();
                if (self._polygonEditorVertexArray.length == 0) {
                    self._drawNodeVertices.drawDot(mapPosition, 5, cc.color.GREEN);
                    self._polygonEditorVertexArray.push(mapPosition);
                }
                self._plot(mapPosition);
                return true;
            },
            onTouchMoved: function (touch, event) {
                if (self._polygonEditorVertexArray.length > 0) {
                    var mapPosition = touch.getLocation();
                    self._plot(mapPosition);
                }
            },
            onTouchEnded: function (touch, event) {
                if (self._polygonEditorVertexArray.length > 0) {
                    var mapPosition = touch.getLocation();
                    if (cc.pDistance(mapPosition, self._polygonEditorVertexArray[self._polygonEditorVertexArray.length - 1]) < 10) {
                        // polyline
                        self._drawNodePoly.clear();
                        self._drawNodeVertices.clear();
                        //
                        var mapPosition = self._mainLayer.getPosition();
                        for (var i = 0; i < self._polygonEditorVertexArray.length; i ++) {
                            self._polygonEditorVertexArray[i] = cc.pSub(self._polygonEditorVertexArray[i], mapPosition);
                        }
                        var polygonlineNode = ObstacleObjectManager.getInstance().createObstacle(self._polygonEditorVertexArray, false);
                        self._worldAddPolylineObstacle(polygonlineNode);
                        self._polygonEditorVertexArray = [];
                    }
                    else if (cc.pDistance(mapPosition, self._polygonEditorVertexArray[0]) < 10) {
                        // polygon
                        self._drawNodePoly.clear();
                        self._drawNodeVertices.clear();
                        //
                        var mapPosition = self._mainLayer.getPosition();
                        for (var i = 0; i < self._polygonEditorVertexArray.length; i ++) {
                            self._polygonEditorVertexArray[i] = cc.pSub(self._polygonEditorVertexArray[i], mapPosition);
                        }
                        var polygonNode = ObstacleObjectManager.getInstance().createObstacle(self._polygonEditorVertexArray);
                        self._worldAddPolygonObstacle(polygonNode);
                        self._polygonEditorVertexArray = [];
                    }
                    else {
                        self._drawNodeVertices.drawDot(mapPosition, 5, cc.color.GREEN);
                        self._polygonEditorVertexArray.push(mapPosition);
                        self._plot();
                    }
                }
            }
        }, this);
    },
    _plot:function(position) {
        this._drawNodePoly.clear();
        if (this._polygonEditorVertexArray.length == 1) {
            this._drawNodePoly.drawSegment(this._polygonEditorVertexArray[0], position, 2, cc.color.RED);
        }
        else if (this._polygonEditorVertexArray.length == 2) {
            if (position) {
                this._drawNodePoly.drawPoly([
                    this._polygonEditorVertexArray[0], this._polygonEditorVertexArray[1], position
                ], cc.color.RED, cc.FLT_EPSILON, cc.color(0, 0, 0, 0));
            }
            else {
                this._drawNodePoly.drawSegment(this._polygonEditorVertexArray[0], this._polygonEditorVertexArray[1], 2, cc.color.RED);
            }
        }
        else {
            var vertexArrayCopy = this._polygonEditorVertexArray.slice();
            if (position) {
                vertexArrayCopy.push(position);
                
            }
            if  (ssr.PolyHelper.isConvex(vertexArrayCopy)) {
                this._drawNodePoly.drawPoly(vertexArrayCopy, cc.color.RED, cc.FLT_EPSILON, cc.color(0, 0, 0, 0));
            }
            else {
                var triangulatePolys = ssr.PolyHelper.triangulate(vertexArrayCopy);
                for (var t = 0, tl = triangulatePolys.length / 3; t < tl; t ++) {
                    var triangle = [triangulatePolys[t * 3], triangulatePolys[t * 3 + 1], triangulatePolys[t * 3 + 2]];
                    this._drawNodePoly.drawPoly(triangle, cc.color.RED, cc.FLT_EPSILON, cc.color(0, 0, 0, 0));
                }   
            }
        }        
    },
    _polyEditorMenuCallback:function(sender, data) {
        if (sender.getSelectedIndex() == 0) {
            this.enablePolyEditor();
        }
        else {
            this.disablePolyEditor();
        }  
    },
    _initFreeDrawingEditor:function() {
        this._vertexArray = [];
        this._drawVertices = new cc.DrawNode();
        this.addChild(this._drawVertices);
        var self = this;
        this._freeDrawingEvent = cc.eventManager.addListener({
            event: cc.EventListener.TOUCH_ONE_BY_ONE,
            swallowTouches: true,
            onTouchBegan: function (touch, event) {
                var touchPosition = touch.getLocation();
                self._vertexArray = [];
                self._drawVertices.clear();
                self._vertexArray.push(touchPosition);
                return true;
            },
            onTouchMoved: function (touch, event) {
                var touchPosition = touch.getLocation();
                var prePosition = self._vertexArray[self._vertexArray.length - 1];
                if (cc.pDistance(prePosition, touchPosition) < 10) {
                    return;
                }
                self._drawVertices.drawSegment(self._vertexArray[self._vertexArray.length - 1], touchPosition, 2, cc.color.WHITE);
                self._vertexArray.push(touchPosition);
            },
            onTouchEnded: function (touch, event) {
                var touchPosition = touch.getLocation();
                self._drawVertices.drawSegment(self._vertexArray[self._vertexArray.length - 1], touchPosition, 2, cc.color.WHITE);
                self._vertexArray.push(touchPosition);

                var touchPosition = self._mainLayer.getPosition();
                for (var i = 0; i < self._vertexArray.length; i ++) {
                    self._vertexArray[i] = cc.pSub(self._vertexArray[i], touchPosition);
                }
                var pathNode = ObstacleObjectManager.getInstance().createObstacle(self._vertexArray, false);
                self._worldAddPolylineObstacle(pathNode);
                self._vertexArray = [];
                self._drawVertices.clear();
            }
        }, this);
    },
    _worldAddPolygonObstacle:function(obstacle) {
        this._mainLayer.addChild(obstacle);
        var obstacleObject = this._robotObject.getLoSComponentCore().addObstacle(obstacle, obstacle.getVertexArray());
        obstacleObject.setVertexArrayProvider(obstacle.getVertexArray);
        obstacleObject.enableDirtyDetection();
        //
        for (var i = 0; i < this._lightSources.length; i ++) {
            this._lightSources[i].getLoSComponentCore().addObstacle(obstacle, obstacle.getVertexArray());
        }
    },
    _worldAddPolylineObstacle:function(obstacle) {
        this._mainLayer.addChild(obstacle);
        this._robotObject.getLoSComponentCore().addObstacle(obstacle, obstacle.getVertexArray(), false);
        for (var i = 0; i < this._lightSources.length; i ++) {
            this._lightSources[i].getLoSComponentCore().addObstacle(obstacle, obstacle.getVertexArray(), false);
        }
    },
    /*********************************** menu callback ***********************************/
    // menu callback
    _followMenuCallback:function(sender, data) {
        if (sender.getSelectedIndex() == 0) {
            this.disableFollow();
        }
        else {
            this.enableFollow();
        }  
    },
    _polyEditorMenuCallback:function(sender, data) {
        if (sender.getSelectedIndex() == 0) {
            this.disablePolyEditor();
        }
        else {
            this.enablePolyEditor();
        }  
    },
    _freeDrawingMenuCallback:function(sender, data) {
        if (sender.getSelectedIndex() == 0) {
            this.disableFreeDrawing();
        }
        else {
            this.enableFreeDrawing();
        }
    },
    _addFlagMenuCallback:function(sender, data) {
        var flag = new cc.Sprite(res.flag_png);
        flag.setPosition(this._robotObject.getPosition());
        flag.setScale(0.3);
        flag.setColor(cc.color.GREEN);
        this._mainLayer.addChild(flag);
        this._targets.push(flag);
        return flag;
    },
    _removeFlagsMenuCallback:function(sender, data) {
        for (var i = 0; i < this._targets.length; i ++) {
            this._targets[i].removeFromParent(true);
        }
        this._targets = [];
    },
    _addLightMenuCallback:function(sender, data) {
        var light = new LightObject(200, 10, 0.6, cc.color(Math.random() * 255, Math.random() * 255, Math.random() * 255, 255));
        this._mainLayer.addChild(light);
        light.setPosition(this._robotObject.getPosition());
        this._lightSources.push(light);
        this._losMaskNode.addTarget(light, light.getLoSComponentCore);
        //
        var obstacles = ObstacleObjectManager.getInstance().getObstacleArray();
        for (var i = 0; i < obstacles.length; i ++) {
            light.getLoSComponentCore().addObstacle(obstacles[i], obstacles[i].getVertexArray(), obstacles[i]._isPolygon);
        }
        return light;
    },
    _removeLightsMenuCallback:function(sender, data) {
        for (var i = 0; i < this._lightSources.length; i ++) {
            this._lightSources[i].removeFromParent(true);
        }
        this._lightSources = [];
    },
    _importMenuCallback:function(sender, data) {
        var input = document.createElement('input');
        input.type = "file";
        input.id = "file";
        input.name = "file";
        var self = this;
        function handleFileSelect(evt) {
            var files = evt.target.files;
            var f = files[0];
            var reader = new FileReader();
            reader.onload = (function(theFile) {
                return function(e) {
                    self._restoreScene(JSON.parse(e.target.result));
                };
            })(f);
            reader.readAsBinaryString(f);
        };
        input.addEventListener('change', handleFileSelect, false);
        input.click();
    },
    _restoreScene:function(schema) {
        // clean first
        // targets
        for (var i = 0; i < this._targets.length; i ++) {
            this._targets[i].removeFromParent(true);
        }
        this._targets = [];
        // lights
        for (var i = 0; i < this._lightSources.length; i ++) {
            this._lightSources[i].removeFromParent(true);
        }
        this._lightSources = [];
        // obstacles
        this._robotObject.getLoSComponentCore().removeAllObstacles();
        this._sightRangeMenuPanelItem.getMenuItem().setSelectedIndex(0);
        this._sightRangeMenuCallback(this._sightRangeMenuPanelItem.getMenuItem());
        // turn off
        if (this._losComponentRenderRay.isEnable()) {
            this._rayRenderMenuPanelItem.getMenuItem().setSelectedIndex(0);
            this._rayRenderMenuCallback(this._rayRenderMenuPanelItem.getMenuItem());
        }
        if (this._losComponentRenderHitPoint.isEnable()) {
            this._hitPointRenderMenuPanelItem.getMenuItem().setSelectedIndex(0);
            this._hitPointRenderMenuCallback(this._hitPointRenderMenuPanelItem.getMenuItem());
        }
        if (this._losComponentRenderPotentialBlockingEdge.isEnable()) {
            this._potentialBlockingEdgeRenderMenuPanelItem.getMenuItem().setSelectedIndex(0);
            this._potentialBlockingEdgeRenderMenuCallback(this._potentialBlockingEdgeRenderMenuPanelItem.getMenuItem());
        }
        if (this._losComponentRenderBlockingEdge.isEnable()) {
            this._blockingEdgeRenderMenuPanelItem.getMenuItem().setSelectedIndex(0);
            this._blockingEdgeRenderMenuCallback(this._blockingEdgeRenderMenuPanelItem.getMenuItem());
        }
        if (this._losComponentRenderVisibleEdge.isEnable()) {
            this._visibleEdgeRRenderMenuPanelItem.getMenuItem().setSelectedIndex(0);
            this._visibleEdgeRenderMenuCallback(this._visibleEdgeRRenderMenuPanelItem.getMenuItem());
        }
        if (this._losComponentRenderSightVert.isEnable()) {
            this._sightVertRenderMenuPanelItem.getMenuItem().setSelectedIndex(0);
            this._sightVertRenderMenuCallback(this._sightVertRenderMenuPanelItem.getMenuItem());
        }
        if (this._losComponentRenderSightRange.isEnable()) {
            this._sightRangeRenderMenuPanelItem.getMenuItem().setSelectedIndex(0);
            this._sightRangeRenderMenuCallback(this._sightRangeRenderMenuPanelItem.getMenuItem());
        }
        if (this._losComponentRenderSightArea.isEnable()) {
            this._sightAreaRenderMenuPanelItem.getMenuItem().setSelectedIndex(0);
            this._sightAreaRenderMenuCallback(this._sightAreaRenderMenuPanelItem.getMenuItem());
        }
        if (this._losComponentRenderSightLight.isEnable()) {
            this._sightLightRenderMenuPanelItem.getMenuItem().setSelectedIndex(0);
            this._sightLightRenderMenuCallback(this._sightLightRenderMenuPanelItem.getMenuItem());
        }
        if (this._losMaskNode.isVisible()) {
            this._losMaskRenderMenuPanelItem.getMenuItem().setSelectedIndex(0);
            this._losMaskRenderMenuCallback(this._losMaskRenderMenuPanelItem.getMenuItem());
        }
        if (this._mainLayer.getNumberOfRunningActions() > 0) {
            this._followPanelItem.getMenuItem().setSelectedIndex(0);
            this._followMenuCallback(this._followPanelItem.getMenuItem());
        }
        // re-init
        //
        this._robotObject.setPosition(schema.robot.x, schema.robot.y);
        this._robotObject.setRotation(schema.robot.rotation);
        if (schema.robot.radius != -1) {
            this._robotObject.getLoSComponentCore().setRadius(schema.robot.radius);
            this._robotObject.getLoSComponentCore().setCentralAngle(schema.robot.centralAngle);
            this._sightRangeMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._sightRangeMenuCallback(this._sightRangeMenuPanelItem.getMenuItem());
        }
        if (schema.robot.sizeLock) {
            this._sightSizeMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._sightSizeMenuCallback(this._sightSizeMenuPanelItem.getMenuItem());
        }
        if (schema.robot.rectLock) {
            this._sightRectMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._sightRectMenuCallback(this._sightRectMenuPanelItem.getMenuItem());       
        }
        // targets
        for (var i = 0; i < schema.targets.length; i ++) {
            var flag = this._addFlagMenuCallback();
            flag.setPosition(schema.targets[i].x, schema.targets[i].y);
        }
        // lights
        for (var i = 0; i < schema.lights.length; i ++) {
            var light = this._addLightMenuCallback();
            light.setPosition(schema.lights[i].x, schema.lights[i].y);
            light.getLoSComponentCore().setRadius(schema.lights[i].radius);
            light._losComponentRenderSightLight.setup(cc.color(schema.lights[i].r, schema.lights[i].g, schema.lights[i].b, schema.lights[i].a), ssr.LoS.Constant.RENDER_NO_BORDER, ssr.LoS.Constant.RENDER_TRANSPARENT, true);
        }
        // obstacles
        for (var i = 0; i < schema.obstacles.length; i ++) {
            if (schema.obstacles[i].isPolygon) {
                var polygonNode = ObstacleObjectManager.getInstance().createObstacle(schema.obstacles[i].vertexes);
                this._worldAddPolygonObstacle(polygonNode);
            }
            else {
                var polygonlineNode = ObstacleObjectManager.getInstance().createObstacle(schema.obstacles[i].vertexes, false);
                this._worldAddPolylineObstacle(polygonlineNode);
            }
        }
        // setting
        if (schema.setting.ray) {
            this._rayRenderMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._rayRenderMenuCallback(this._rayRenderMenuPanelItem.getMenuItem());
        }
        if (schema.setting.hitPoint) {
            this._hitPointRenderMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._hitPointRenderMenuCallback(this._hitPointRenderMenuPanelItem.getMenuItem());
        }
        if (schema.setting.potentialBlockingEdge) {
            this._potentialBlockingEdgeRenderMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._potentialBlockingEdgeRenderMenuCallback(this._potentialBlockingEdgeRenderMenuPanelItem.getMenuItem());
        }
        if (schema.setting.blockingEdge) {
            this._blockingEdgeRenderMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._blockingEdgeRenderMenuCallback(this._blockingEdgeRenderMenuPanelItem.getMenuItem());
        }
        if (schema.setting.visibleEdge) {
            this._visibleEdgeRRenderMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._visibleEdgeRenderMenuCallback(this._visibleEdgeRRenderMenuPanelItem.getMenuItem());
        }
        if (schema.setting.sightVert) {
            this._sightVertRenderMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._sightVertRenderMenuCallback(this._sightVertRenderMenuPanelItem.getMenuItem());
        }
        if (schema.setting.sightRange) {
            this._sightRangeRenderMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._sightRangeRenderMenuCallback(this._sightRangeRenderMenuPanelItem.getMenuItem());
        }
        if (schema.setting.sightArea) {
            this._sightAreaRenderMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._sightAreaRenderMenuCallback(this._sightAreaRenderMenuPanelItem.getMenuItem());
        }
        if (schema.setting.sightLight) {
            this._sightLightRenderMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._sightLightRenderMenuCallback(this._sightLightRenderMenuPanelItem.getMenuItem());
        }
        if (schema.setting.mask) {
            this._losMaskRenderMenuPanelItem.getMenuItem().setSelectedIndex(1);
            this._losMaskRenderMenuCallback(this._losMaskRenderMenuPanelItem.getMenuItem());
        }
        if (schema.setting.follow) {
            this._followPanelItem.getMenuItem().setSelectedIndex(1);
            this._followMenuCallback(this._followPanelItem.getMenuItem());
        }
    },
    _exportMenuCallback:function(sender, data) {
        var schema = {};
        schema.map = {};
        schema.robot = {};
        schema.lights = [];
        schema.targets = [];
        schema.obstacles = [];
        schema.setting = {};
        //
        schema.map.width = this._mainLayer.width;
        schema.map.height = this._mainLayer.height;
        //
        schema.robot.x = this._robotObject.x;
        schema.robot.y = this._robotObject.y;
        schema.robot.rotation = this._robotObject.getRotation();
        schema.robot.radius = this._robotObject.getLoSComponentCore().getRadius();
        schema.robot.centralAngle = this._robotObject.getLoSComponentCore().getCentralAngle();
        if (!this._robotObject.getLoSComponentCore().isAutoGenerateBoundary()) {
            if (this._robotObject.getLoSComponentCore().isLockSightBoundary()) {
                schema.robot.rectLock = true;
            }
            else {
                schema.robot.sizeLock = true;   
            }
        }
        //
        for (var i = 0; i < this._lightSources.length; i ++) {
            schema.lights.push(
                {
                    "x"             : this._lightSources[i].x,
                    "y"             : this._lightSources[i].y,
                    "r"             : this._lightSources[i]._lightColor.r,
                    "g"             : this._lightSources[i]._lightColor.g,
                    "b"             : this._lightSources[i]._lightColor.b,
                    "a"             : this._lightSources[i]._lightColor.a,
                    "radius"        : this._lightSources[i]._range
                }
            );
        }
        //
        for (var i = 0; i < this._targets.length; i ++) {
            schema.targets.push(
                {
                    "x"     : this._targets[i].x,
                    "y"     : this._targets[i].y
                }
            );
        }
        //
        var obstacles = ObstacleObjectManager.getInstance().getObstacleArray();
        for (var i = 0; i < obstacles.length; i ++) {
            var vertexArray = obstacles[i].getVertexArray();
            schema.obstacles.push(
                {
                    "vertexes"  : vertexArray,
                    "isPolygon" : obstacles[i]._isPolygon
                }
            );   
        }
        //
        schema.setting = {
            "ray"                       : this._losComponentRenderRay.isEnable(),
            "hitPoint"                  : this._losComponentRenderHitPoint.isEnable(),
            "potentialBlockingEdge"     : this._losComponentRenderPotentialBlockingEdge.isEnable(),
            "blockingEdge"              : this._losComponentRenderBlockingEdge.isEnable(),
            "visibleEdge"               : this._losComponentRenderVisibleEdge.isEnable(),
            "sightVert"                 : this._losComponentRenderSightVert.isEnable(),
            "sightRange"                : this._losComponentRenderSightRange.isEnable(),
            "sightArea"                 : this._losComponentRenderSightArea.isEnable(),
            "sightLight"                : this._losComponentRenderSightLight.isEnable(),
            "mask"                      : this._losMaskNode.isVisible(),
            "follow"                    : this._mainLayer.getNumberOfRunningActions() > 0 ? true : false
        };
        //
        window.saveAs(new Blob([JSON.stringify(schema)]), (new Date().getTime()) + ".json");
    },
    /*********************************** menu logic ***********************************/
    disableFollow:function() {
        this._mainLayer.stopAllActions();
    },
    enableFollow:function() {
        this._mainLayer.runAction(
            cc.Follow.create(
                this._robotObject, 
                cc.rect(0, 0, this._mainLayer.width, this._mainLayer.height)
            )
        );
    },
    enablePolyEditor:function() {
        this._initPolygonEditor();
        this._freeDrawingMenuPanelItem._menuItem.setSelectedIndex(0);
        this.disableFreeDrawing();
        if (this.joyStickLayer) {
            this.joyStickLayer.disable();
        }
    },
    disablePolyEditor:function() {
        if (this._polygonEditorEvent) {
            this._polygonEditorVertexArray = [];
            this._drawNodePoly.removeFromParent(true);
            this._drawNodeVertices.removeFromParent(true);
            cc.eventManager.removeListener(this._polygonEditorEvent);
            this._polygonEditorEvent = null;
        }
        if (this.joyStickLayer) {
            this.joyStickLayer.enable();
        }
    },
    enableFreeDrawing:function() {
        this._initFreeDrawingEditor();
        this._polyEditorMenuPanelItem._menuItem.setSelectedIndex(0);
        this.disablePolyEditor();
        if (this.joyStickLayer) {
            this.joyStickLayer.disable();
        }
    },
    disableFreeDrawing:function() {
        if (this._freeDrawingEvent) {
            cc.eventManager.removeListener(this._freeDrawingEvent);
            this._freeDrawingEvent = null;
        }
        if (this.joyStickLayer) {
            this.joyStickLayer.enable();
        }
    }
});
